package com.ltu.util.http;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.bcel.Const;

import javax.net.ssl.SSLContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import lombok.extern.slf4j.Slf4j;

/**
 * HttpRequestUtil 工具类
 * 
 *兼容http和https不验证域名和证书
 */

@Component
@Slf4j
public class HttpRequestUtil {
	@Autowired
	private	CloseableHttpClient httpClient;
	public  String post(String url, String requestBody){
		String responseBody = null;
		try {
			// Post请求
			HttpPost httppost = new HttpPost(url);
			httppost.setHeader("Content-Type", "application/json");
			// 设置参数
			if(StringUtils.isNotBlank(requestBody)) {
				System.out.println("requestBody:" + requestBody);
				httppost.setEntity(new StringEntity(requestBody,"UTF-8"));
			}
			// 发送请求
			HttpResponse httpresponse = httpClient.execute(httppost);
			// 获取返回数据
			HttpEntity entity = httpresponse.getEntity();
			responseBody = EntityUtils.toString(entity);
			System.out.println("responseBody:" + responseBody);
			if (entity != null) {
				EntityUtils.consume(entity);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return responseBody;
	}
	
	public  ClientResponse postSSL(String url, String resquestBody, String keyStorePath,
            String keyStorePassword) {
        SSLContext sslcontext = sslContext(keyStorePath, keyStorePassword);
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                // 正常的SSL连接会验证码所有证书信息
                // .register("https", new SSLConnectionSocketFactory(sslcontext)).build();
                //  只忽略域名验证码
                .register("https", new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE)).build();
            
        HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        HttpClients.custom().setConnectionManager(connManager);
        ClientResponse  rsp =  new ClientResponse();
        try ( // 创建post方式请求对象
                CloseableHttpClient client = HttpClients.custom().
                setConnectionManager(connManager).build();) {
            // 设置连接超时时间
            RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(60)
                    .setConnectTimeout(120).setSocketTimeout(120).build();
            // 创建httpclient对象
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            // 2 直接是拼接好的key=value或者json字符串等
            httpPost.setEntity(new StringEntity(resquestBody, Consts.UTF_8));
            // 执行请求操作，并拿到结果
            CloseableHttpResponse response = client.execute(httpPost);
            // 获取响应头
            Header[] rspHeaders = response.getAllHeaders();
            if (ArrayUtils.isNotEmpty(rspHeaders)) {
                Map<String, String> tmp = new HashMap<>();
                for (Header header : rspHeaders) {
                    tmp.put(header.getName(), header.getValue());
                }
            }
            // 响应码
            rsp.setResponseCode(response.getStatusLine().getStatusCode());
            // 获取结果实体
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                /*
                 * 按指定编码转换结果实体为String类型。 如果这行报错 connection
                 * reset，那么有可能是链路不通或者post的url过长。
                 */
                String body = EntityUtils.toString(entity,  Consts.UTF_8);
                rsp.setResponseContent(body);
            }
            // 关闭流
            EntityUtils.consume(entity);
            // 释放链接
            response.close();
            // 关闭客户端
            client.close();
        } catch (Exception e) {
            log.error("请求出错", e);
        }
        return rsp;
    }

    /**
     * 设置信任自签名证书
     * 
     * @param keyStorePath
     *            密钥库路径
     * @param keyStorepass
     *            密钥库密码
     * @return
     */
    public  SSLContext sslContext(String keyStorePath, String keyStorepass) {
       SSLContext sc = null;
        FileInputStream instream = null;
        KeyStore trustStore = null;
        try {
            trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            // 加载密钥库
            instream = new FileInputStream(new File(keyStorePath));
            trustStore.load(instream, keyStorepass.toCharArray());
            // 相信自己的CA和所有自签名的证书
            sc = SSLContexts.custom().loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build();
        } catch (Exception e) {
            log.error("HTTPS请求初始化SSL异常", e);
        } finally {
        	try {
				instream.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        }
        return sc;
    }
	
}
